#ifndef __MV_DATA_TYPES
#define __MV_DATA_TYPES

#if defined(__BORLAND)
  #define GV_EXTERN       extern "C"
  #define GV_DECLSPEC     WINAPI
  #define DECLSPEC_PT     _cdecl
  #define DECLSPEC        WINAPI
#else
#if defined(__MSOFT) || defined(__INTEL) || defined(__DMC)
  #define GV_EXTERN       extern "C"
  #define GV_DECLSPEC     WINAPI
  #define DECLSPEC_PT     _cdecl
  #define DECLSPEC        WINAPI
#else
  #error "Unknown platform"
#endif //MS, Intel, Dmc
#endif //BC

#define RSIZE_DMS                 4
#define RSIZE_DM                  6
#define RSIZE_D                   8

#define COORD_STR_SIZE            20

#define Error_Datum_Index         -1
#define Default_Datum_Index       -100

#define Default_CoordinateSystem  ((Coordinate_Type)(-100))
#define MAX_CoordinateSystem      ((Coordinate_Type)(CoordSUnknown+0))

#define UNKNOWN_ALTITUDE          (-777)
#define UNKNOWN_DIR               (-1)

#define MIN_ZOOM_PC               5
#define MAX_ZOOM_PC               1000

enum degTypes_t {
  dtDMS,
  dtDM,
  dtD,
  dtMAX = dtD+1
};
typedef short degTypes;

/* -----------------------------------------------------
   BASE TYPES
*/
#if defined( __BCB__ )
  typedef void __fastcall(__closure *MVIndexEvent)( int Index );
  typedef void __fastcall(__closure *MVSimpleEvent)( void );
#else
#if defined( __MSWIN32__ )
  typedef struct { BYTE data[ sizeof(LPVOID)*2 /*this + class ptr*/ ]; } MVIndexEvent;
  typedef struct { BYTE data[ sizeof(LPVOID)*2 /*this + class ptr*/ ]; } MVSimpleEvent;
#else
  #error "Unknown platform!"
#endif  //MS
#endif  //BC

typedef MyValArray<MVIndexEvent> MVIndexEvents;

/* -----------------------------------------------------
   COORD TYPES
*/
#if 1
  #define GC_FMT  "lf"
  typedef double GINT;

  #define SYS_COORDSYS              Geodetic
  #define SYS_DATUM                 WGS84_Datum_Index

  #define DELTA_G                   0.0000001
  #define MAX_G_X                   (180.-DELTA_G)
  #define MIX_G_X                   (-MAX_G_X)
  #define MAX_G_Y                   (90.-DELTA_G)
  #define MIX_G_Y                   (-MAX_G_Y)
#else
  #define GC_FMT  "lf"
  typedef double GINT;

  #define SYS_COORDSYS              Equidistant_Cylindrical
  #define SYS_DATUM                 WGS84_Datum_Index

  #define DELTA_G                   0.5
  #define MAX_G_X                   20015110.0
  #define MIX_G_X                   -20015110.0
  #define MAX_G_Y                   10007555.0
  #define MIX_G_Y                   -10007555.0
#endif
typedef GINT    GCoord_t;

//---------------------------------------------------------------------------
LOCALSTRUCT( GPoint )
  GCoord_t x, y;

  void     Set( GCoord_t _x, GCoord_t _y ) { x = _x; y = _y; }
  void     Set( const GPoint p )           { x = p.x; y = p.y; }

  void     Zero( void )                    { x = y = 0; }
  bool     isNull( void )                  { return Abs(x) < DELTA_G && Abs(y) < DELTA_G; }

  bool     Equal( const GPoint& p )               const { return x == p.x && y == p.y; }
  bool     Equal( const GPoint& p, GCoord_t off ) const { return Abs(x-p.x) < off && Abs(y-p.y) < off; }
};

/* NE coordinates
*/
STRUCT( NEPoint )
  double n,e;
};

/* Geodetic coordinates
*/
LOCALSTRUCT( GLLPoint )
  double x,    //Longitude  -180...180
         y;    //Latitude   -90..90

  void Set( double _x, double _y ) { x = _x; y = _y; }
  void Set( const GLLPoint& p )    { x = p.x; y = p.y; }
};

/* Link raster and G coordinates
*/
STRUCT( GMapPoint )
  int      x,y;      //Raster point
  NEPoint  ne;       //Coords in NE form      (used if CoordSys!=Geodetic)
  GPoint   g;        //Coords in system type  (used if CoordSys==Geodetic)
};

//---------------------------------------------------------------------------
LOCALSTRUCT( GRect )
  GCoord_t x, y, x1, y1;

  void Zero( void )                         { x = y = x1 = y1 = 0; }
  void Set( GCoord_t _x, GCoord_t _y )      { x = _x; y = _y; x1 = _x; y1 = _y; }
  void Set( GCoord_t _x, GCoord_t _y,
            GCoord_t _x1, GCoord_t _y1 )    { x = _x; y = _y; x1 = _x1; y1 = _y1; }
  void SetAroundPoint( GCoord_t _x, GCoord_t _y,
                       GCoord_t dx, GCoord_t dy ) { x = _x-dx; y = _y-dy; x1 = _x+dx; y1 = _y+dy; }

  void Normalize( void )                    { if ( x > x1 ) Swap(x,x1); if ( y > y1 ) Swap(y,y1); }

  bool Contains( GCoord_t px, GCoord_t py )     const { return !(px < x || px > x1 || py < y || py >y1); }
  bool Contains( const GPoint& p )              const { return !(p.x < x || p.x > x1 || p.y < y || p.y >y1); }

  GCoord_t Width( void )                        const { return x1-x; }
  GCoord_t Height( void )                       const { return y1-y; }
};

LOCALSTRUCT( GLLRect )
  double x, y,
         x1, y1;

  void     Normalize( void )                    { if ( x > x1 ) Swap(x,x1); if ( y > y1 ) Swap(y,y1); }
  GCoord_t Width( void )                  const { return x1-x; }
  GCoord_t Height( void )                 const { return y1-y; }
};

//---------------------------------------------------------------------------
LOCALSTRUCTBASE( GPosition, public GPoint )
  double   Altitude;   //UNKNOWN_ALTITUDE
  double   Course;     //UNKNOWN_DIR
  double   Speed;
  GLLPoint Position;

  GPosition( void )               { Position.Set(0,0); x = y = 0; Speed = 0; Altitude = UNKNOWN_ALTITUDE; Course = UNKNOWN_DIR; }
  GPosition( const GPoint& p )    { Set(p); }
  GPosition( const GPosition& p ) { Set(p); }

  void Set( GCoord_t _x, GCoord_t _y, double dir ) { GPoint::Set( _x,_y); Course = dir; }
  void Set( const GPoint& p )      { Position.Set(0,0); x = p.x; y = p.y; Speed = 0; Altitude = UNKNOWN_ALTITUDE; Course = UNKNOWN_DIR; }
  void Set( const GPosition& p )   { Position.Set(0,0); x = p.x; y = p.y; Speed = p.Speed; Altitude = p.Altitude; Course = p.Course; }
};

//---------------------------------------------------------------------------
/* Map bounds
*/
//[GDUtils/gdu_utils.cpp]
STRUCT( GBounds )
  GPoint tl, //top-left
         tr, //top-right
         br, //bottom-right
         bl; //bottom-left

  GBounds( void );
  GBounds( const GBounds& p );

  void Set( const GBounds& p );

  void GetRect( GRect& r, bool ismax = true ) const;
  bool Contains( const GPoint& p, bool ismax = true ) const;
};

STRUCT( MVBoundPoint )
  int      x, y;
  double   gX, gY;  //Lat/Lon
  GPoint   g;
};

//[GDUtils/gdu_utils.cpp]
CLASSBASE( MVBounds, public MyRefArray<MVBoundPoint> )
  public:
    MVBounds( void );
    MVBounds( const MVBounds& p );

    void Set( const MVBounds& p );

    bool Contains( const GPoint& p );
    bool Contains( const MyPoint& p );
};

//---------------------------------------------------------------------------
/* Point describe coordinate in any coordinate system
   Can be in Lat/Lon and N/E form
*/
STRUCT( OZIMapPoint )
  int    x,y;           // raster point

  bool   isLatLon;

  double gY;            // isLatLon == true
  char   SN;
  double gX;
  char   WE;

  int    e, n;          // isLatLon == false
  char   hemisphere;
};

//[GDUtils/gdu_utils.cpp]
STRUCT( MVProjectionInfo )
  double  origin_latitude;   /* radians */
  double  central_meridian;  /* radians */
  double  std_parallel_1;    /* radians */
  double  std_parallel_2;    /* radians */
  double  scale;
  double  false_easting;     /* meters */
  double  false_northing;    /* meters */
  double  height;

  void SetDefault( void );
};

#endif